package com.ruicar.afs.cloud.basic.common.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.common.entity.BasicAssetsRepaymentPlan;
import com.ruicar.afs.cloud.basic.common.entity.BasicReceiptDealDetails;
import com.ruicar.afs.cloud.basic.common.entity.BasicReceiptDealLine;
import com.ruicar.afs.cloud.basic.common.entity.BasicRepaymentPlan;
import com.ruicar.afs.cloud.basic.common.mapper.BasicAssetsRepaymentPlanMapper;
import com.ruicar.afs.cloud.basic.common.service.BasicAssetsRepaymentPlanService;
import com.ruicar.afs.cloud.basic.common.service.BasicReceiptDealLineService;
import com.ruicar.afs.cloud.common.modules.contract.enums.RepaymentStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.WriteTargetTypeEnum;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:35:07
 * @description
 */
@Service
@AllArgsConstructor
public class BasicAssetsRepaymentPlanServiceImpl extends ServiceImpl<BasicAssetsRepaymentPlanMapper, BasicAssetsRepaymentPlan> implements BasicAssetsRepaymentPlanService {

    private final BasicReceiptDealLineService basicReceiptDealLineService;

    @Override
    public void handleInterest(BasicReceiptDealDetails receiptDealDetails,BasicRepaymentPlan repaymentPlan, BigDecimal amount, BigDecimal actualAmount, BigDecimal receivableAmount, WriteTargetTypeEnum writeTarget, Date batchDate) {

        List<RepaymentStatusEnum> statusEnumList = new ArrayList<>();
        statusEnumList.add(RepaymentStatusEnum.UNPAID);
        statusEnumList.add(RepaymentStatusEnum.OVERDUE);

        List<BasicAssetsRepaymentPlan> assetsRepaymentPlanList = this.list(Wrappers.<BasicAssetsRepaymentPlan>query().lambda()
                .eq(BasicAssetsRepaymentPlan::getContractNo, repaymentPlan.getContractNo())
                .eq(BasicAssetsRepaymentPlan::getTermNo, repaymentPlan.getTermNo())
                .in(BasicAssetsRepaymentPlan::getStatus, statusEnumList)
        );
        if (assetsRepaymentPlanList != null && assetsRepaymentPlanList.size() > 0) {
            int currentSeq = 1;
            int totalNum = assetsRepaymentPlanList.size();
            BigDecimal usedAmt = BigDecimal.ZERO;
            for (BasicAssetsRepaymentPlan assetsRepaymentPlan : assetsRepaymentPlanList) {
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualRent())) {
                    assetsRepaymentPlan.setActualRent(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualInterest())) {
                    assetsRepaymentPlan.setActualInterest(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualPrinciple())) {
                    assetsRepaymentPlan.setActualPrinciple(BigDecimal.ZERO);
                }
                /**  可用金额大于0 by ZC.GUO  **/
                if (amount.compareTo(usedAmt) > 0) {
                    /**  本条计划还款计划本次应核销金额 by ZC.GUO  **/
                    BigDecimal thisNeedAmt = BigDecimal.ZERO;
                    BigDecimal thisAmt = BigDecimal.ZERO;

                    /**  最后一条倒减 by ZC.GUO  **/
                    if (currentSeq == totalNum && amount.compareTo(usedAmt) > 0) {
                        thisNeedAmt = amount.subtract(usedAmt);
                    } else {
                        /**  本记录实应收利息 = 本记录本期应收*本合同本期实应收/本合同本期应收 by ZC.GUO  **/
                        BigDecimal actualReceivable = assetsRepaymentPlan.getReceivableInterest().multiply(repaymentPlan.getReceivableInterest().divide(receivableAmount, 2, BigDecimal.ROUND_UP));

                        /**  本记录本次应收利息 = （本记录实应收利息*本合同本期总已收利息/本合同本期总应收利息）-本记录已收利息 by ZC.GUO  **/
                        thisNeedAmt = actualAmount.divide(receivableAmount, 2, BigDecimal.ROUND_UP).multiply(actualReceivable).subtract(assetsRepaymentPlan.getActualInterest()).setScale(2, BigDecimal.ROUND_UP);
                        currentSeq++;
                    }
                    /**  最终核销金额 by ZC.GUO  **/
                    thisAmt = thisNeedAmt.compareTo(amount.subtract(usedAmt)) > 0 ? amount.subtract(usedAmt) : thisNeedAmt;
                    usedAmt = usedAmt.add(thisAmt);

                    assetsRepaymentPlan.setActualRent(assetsRepaymentPlan.getActualRent().add(thisAmt));
                    assetsRepaymentPlan.setActualInterest(assetsRepaymentPlan.getActualInterest().add(thisAmt));

                    /**  租金状态判断 by ZC.GUO  **/
                    if (thisAmt.compareTo(BigDecimal.ZERO)>0){
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    if (assetsRepaymentPlan.getReceivableRent().compareTo(assetsRepaymentPlan.getActualRent()) <= 0) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.REPAID);
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    /**  如果是提前还款，并且所有本金已核销 by ZC.GUO  **/
                    if (WriteTargetTypeEnum.beforeCharge.equals(writeTarget) && assetsRepaymentPlan.getRemainPrinciple().compareTo(assetsRepaymentPlan.getActualPrinciple()) <= 0) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.PREPAYMENT);
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    this.updateById(assetsRepaymentPlan);
                    /**  记录明细流水对照 by ZC.GUO  **/
                    BasicReceiptDealLine dealLine = new BasicReceiptDealLine();
                    dealLine.setReceiptId(receiptDealDetails.getReceiptId());
                    dealLine.setDetailId(receiptDealDetails.getId());
                    dealLine.setDealTable(assetsRepaymentPlan.getClass().getAnnotation(TableName.class).value());
                    dealLine.setDealId(assetsRepaymentPlan.getId());
                    dealLine.setDealAmt(thisAmt);
                    basicReceiptDealLineService.save(dealLine);

                }
            }
        }

    }

    @Override
    public void handlePrinciple(BasicReceiptDealDetails receiptDealDetails,BasicRepaymentPlan repaymentPlan, BigDecimal amount, BigDecimal actualAmount, BigDecimal receivableAmount, WriteTargetTypeEnum writeTarget, Date batchDate) {
        List<RepaymentStatusEnum> statusEnumList = new ArrayList<>();
        statusEnumList.add(RepaymentStatusEnum.UNPAID);
        statusEnumList.add(RepaymentStatusEnum.OVERDUE);

        List<BasicAssetsRepaymentPlan> assetsRepaymentPlanList = this.list(Wrappers.<BasicAssetsRepaymentPlan>query().lambda()
                .eq(BasicAssetsRepaymentPlan::getContractNo, repaymentPlan.getContractNo())
                .eq(BasicAssetsRepaymentPlan::getTermNo, repaymentPlan.getTermNo())
                .in(BasicAssetsRepaymentPlan::getStatus, statusEnumList)
        );
        if (assetsRepaymentPlanList != null && assetsRepaymentPlanList.size() > 0) {
            int currentSeq = 1;
            int totalNum = assetsRepaymentPlanList.size();
            BigDecimal usedAmt = BigDecimal.ZERO;
            for (BasicAssetsRepaymentPlan assetsRepaymentPlan : assetsRepaymentPlanList) {
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualRent())) {
                    assetsRepaymentPlan.setActualRent(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualInterest())) {
                    assetsRepaymentPlan.setActualInterest(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(assetsRepaymentPlan.getActualPrinciple())) {
                    assetsRepaymentPlan.setActualPrinciple(BigDecimal.ZERO);
                }
                /**  可用金额大于0 by ZC.GUO  **/
                if (amount.compareTo(usedAmt) > 0) {
                    /**  本条计划还款计划本次应核销金额 by ZC.GUO  **/
                    BigDecimal thisNeedAmt = BigDecimal.ZERO;
                    BigDecimal thisAmt = BigDecimal.ZERO;

                    /**  最后一条倒减 by ZC.GUO  **/
                    if (currentSeq == totalNum && amount.compareTo(usedAmt) > 0) {
                        thisNeedAmt = amount.subtract(usedAmt);
                    } else {
                        /**  本记录本次应收本金 = （本记录应收本金*本合同本期总已收本金/本合同本期总应收本金）-本记录已收本金 by ZC.GUO  **/
                        thisNeedAmt = actualAmount.divide(receivableAmount, 2, BigDecimal.ROUND_UP).multiply(assetsRepaymentPlan.getReceivablePrinciple()).subtract(assetsRepaymentPlan.getActualPrinciple()).setScale(2, BigDecimal.ROUND_UP);
                        currentSeq++;
                    }
                    /**  最终核销金额 by ZC.GUO  **/
                    thisAmt = thisNeedAmt.compareTo(amount.subtract(usedAmt)) > 0 ? amount.subtract(usedAmt) : thisNeedAmt;
                    usedAmt = usedAmt.add(thisAmt);

                    assetsRepaymentPlan.setActualRent(assetsRepaymentPlan.getActualRent().add(thisAmt));
                    assetsRepaymentPlan.setActualPrinciple(assetsRepaymentPlan.getActualPrinciple().add(thisAmt));

                    /**  租金状态判断 by ZC.GUO  **/
                    if (thisAmt.compareTo(BigDecimal.ZERO)>0){
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    if (assetsRepaymentPlan.getReceivableRent().compareTo(assetsRepaymentPlan.getActualRent()) <= 0) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.REPAID);
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    /**  如果是提前还款，并且所有本金已核销 by ZC.GUO  **/
                    if (WriteTargetTypeEnum.beforeCharge.equals(writeTarget) && assetsRepaymentPlan.getRemainPrinciple().compareTo(assetsRepaymentPlan.getActualPrinciple()) <= 0) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.PREPAYMENT);
                        assetsRepaymentPlan.setActualDate(batchDate);
                    }
                    this.updateById(assetsRepaymentPlan);
                    /**  记录明细流水对照 by ZC.GUO  **/
                    BasicReceiptDealLine dealLine = new BasicReceiptDealLine();
                    dealLine.setReceiptId(receiptDealDetails.getReceiptId());
                    dealLine.setDetailId(receiptDealDetails.getId());
                    dealLine.setDealTable(assetsRepaymentPlan.getClass().getAnnotation(TableName.class).value());
                    dealLine.setDealId(assetsRepaymentPlan.getId());
                    dealLine.setDealAmt(thisAmt);
                    basicReceiptDealLineService.save(dealLine);

                }
            }
        }
    }

    @Override
    public void cancelInterest(Long receiptDetailId,BasicRepaymentPlan repaymentPlan, Date batchDate) {

        List<BasicAssetsRepaymentPlan> assetsRepaymentPlanList = this.list(Wrappers.<BasicAssetsRepaymentPlan>query().lambda()
                .eq(BasicAssetsRepaymentPlan::getContractNo, repaymentPlan.getContractNo())
                .eq(BasicAssetsRepaymentPlan::getTermNo, repaymentPlan.getTermNo())
        );
        if (assetsRepaymentPlanList != null && assetsRepaymentPlanList.size() > 0) {
            for (BasicAssetsRepaymentPlan assetsRepaymentPlan : assetsRepaymentPlanList) {
                BasicReceiptDealLine dealLine = basicReceiptDealLineService.getOne(Wrappers.<BasicReceiptDealLine>query().lambda()
                        .eq(BasicReceiptDealLine::getDetailId,receiptDetailId)
                        .eq(BasicReceiptDealLine::getDealId,assetsRepaymentPlan.getId())
                        .eq(BasicReceiptDealLine::getDealTable,assetsRepaymentPlan.getClass().getAnnotation(TableName.class).value())
                );
                /**  流水对照金额大于0 by ZC.GUO  **/
                if (EmptyUtils.isNotEmpty(dealLine) && dealLine.getDealAmt().compareTo(BigDecimal.ZERO)>0) {
                    BigDecimal needAmount = dealLine.getDealAmt();
                    assetsRepaymentPlan.setActualRent(assetsRepaymentPlan.getActualRent().subtract(needAmount));
                    assetsRepaymentPlan.setActualInterest(assetsRepaymentPlan.getActualInterest().subtract(needAmount));
                    assetsRepaymentPlan.setActualDate(null);

                    /**  租金状态判断 by ZC.GUO  **/
                    if (assetsRepaymentPlan.getDueDate().before(DateUtil.beginOfDay(batchDate))) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.OVERDUE);
                    } else {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.UNPAID);
                    }
                    this.baseMapper.updateActualDate(assetsRepaymentPlan.getContractNo(), assetsRepaymentPlan.getTermNo());
                    this.updateById(assetsRepaymentPlan);
                }
            }
        }
    }

    @Override
    public void cancelPrinciple(Long receiptDetailId,BasicRepaymentPlan repaymentPlan, Date batchDate) {
        List<BasicAssetsRepaymentPlan> assetsRepaymentPlanList = this.list(Wrappers.<BasicAssetsRepaymentPlan>query().lambda()
                .eq(BasicAssetsRepaymentPlan::getContractNo, repaymentPlan.getContractNo())
                .eq(BasicAssetsRepaymentPlan::getTermNo, repaymentPlan.getTermNo())
        );
        if (assetsRepaymentPlanList != null && assetsRepaymentPlanList.size() > 0) {
            for (BasicAssetsRepaymentPlan assetsRepaymentPlan : assetsRepaymentPlanList) {
                /**  可用金额大于0 by ZC.GUO  **/
                BasicReceiptDealLine dealLine = basicReceiptDealLineService.getOne(Wrappers.<BasicReceiptDealLine>query().lambda()
                        .eq(BasicReceiptDealLine::getDetailId,receiptDetailId)
                        .eq(BasicReceiptDealLine::getDealId,assetsRepaymentPlan.getId())
                        .eq(BasicReceiptDealLine::getDealTable,assetsRepaymentPlan.getClass().getAnnotation(TableName.class).value())
                );
                if (EmptyUtils.isNotEmpty(dealLine) && dealLine.getDealAmt().compareTo(BigDecimal.ZERO)>0) {
                    BigDecimal needAmount = dealLine.getDealAmt();
                    assetsRepaymentPlan.setActualRent(assetsRepaymentPlan.getActualRent().subtract(needAmount));
                    assetsRepaymentPlan.setActualPrinciple(assetsRepaymentPlan.getActualPrinciple().subtract(needAmount));
                    assetsRepaymentPlan.setActualDate(null);

                    /**  租金状态判断 by ZC.GUO  **/
                    if (assetsRepaymentPlan.getDueDate().before(DateUtil.beginOfDay(batchDate))) {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.OVERDUE);
                    } else {
                        assetsRepaymentPlan.setStatus(RepaymentStatusEnum.UNPAID);
                    }
                    this.baseMapper.updateActualDate(assetsRepaymentPlan.getContractNo(), assetsRepaymentPlan.getTermNo());
                    this.updateById(assetsRepaymentPlan);
                }
            }
        }
    }
}
